﻿
#include "GActivityGoblin.h"
#include "ServerModule/LogicActivityModule.h"
#include "Character/CreatureMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/npc/Npc.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/drop/DropMgr.h"
#include "Common/TableData/MonsterMonsterCfg.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Common/OperateLimitDefine.h"
#include "Character/HuoYueDuPart.h"
#include "Common/EventDefine.h"
GActivityGoblin::GActivityGoblin()
{
	Clear();
	ClearUnionParam();
}

GActivityGoblin::~GActivityGoblin()
{

}

void GActivityGoblin::Clear()
{
	m_freshBoss = false;
	m_recycleNum = 0;
	m_freshNum = 0;
	m_mapNpc.clear();
	m_cfg.clear();
	m_bossCid = 0;
	m_setHarmChar.clear();
	m_mapPlanRelate.clear();
	m_bNotifyMonsAllDie = false;
	m_setWaitPlan.clear();
}

//清空工会参数
void GActivityGoblin::ClearUnionParam()
{
	m_unionId = 0;
	m_sceneId = 0;
	m_mapId = 0;
	m_lev = 0;
	m_averageLev = 0;
	m_vaultLev = 0;
}

Monster *GActivityGoblin::GetSceneMonster(CharIDType cid)			//获取怪物
{
	return g_GetSceneMgr()->GetMonster(m_sceneId, cid);
}

Npc *GActivityGoblin::GetSceneNpc(CharIDType cid)					//获取npc
{
	return g_GetSceneMgr()->GetNpc(m_sceneId, cid);
}

Creature*GActivityGoblin::GetSceneCreature(CharIDType cid)				//获取玩家
{
	return g_GetSceneMgr()->GetCreature(m_sceneId, cid);
}
Player*GActivityGoblin::GetScenePlayer(CharIDType cid) //获取玩家
{
	return g_GetSceneMgr()->GetPlayer(m_sceneId, cid);
}

void GActivityGoblin::Init(uint32_t activityId)
{
	GActivity::Init(activityId);
}

void GActivityGoblin::UnInit()
{
	GActivity::UnInit();
	OnActivityStop();
}

bool GActivityGoblin::Update()
{
	if (IsRuning())
	{
		OnPlanDestory();
	}
	return true;
}

void GActivityGoblin::OnActivityStart()
{
	//先清空数据
	Clear();
	//读取lua配置
	if (!g_GetGActivityMgr()->LuaGetGoblinCfg(m_cfg,m_vaultLev))
	{
		m_cfg.clear();
		return;
	}
	g_GetTimerAxis()->KillTimer(ETimer_ID_Check, this);
	g_GetTimerAxis()->SetTimer(ETimer_ID_Check,1 * 1000,this);

	g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, 0, CREATURE_MONSTER, "GActivityGoblin");
	g_GetEvent()->Subscribe(this, EVENT_PLANE_CLOSE, 0, CREATURE_PLAYER, "GActivityGoblin");
	g_GetEvent()->Subscribe(this, EVENT_PLANE_LEAVE, 0, CREATURE_PLAYER, "GActivityGoblin");
	
}



void GActivityGoblin::OnActivityStop()
{
	g_GetEvent()->UnSubscribeAll(this);
	g_GetTimerAxis()->KillAllTimer(this);
	OnPlanDestory();
	RecycleNpcAndMonster();
	Clear();
	ClearUnionParam();
}


void  GActivityGoblin::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Check:
		{
			uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
			//先检查刷新NPC
			FreshNpc(curTime);
			//再检查生存时间
			CheckNpc(curTime);
		}
		break;
	case ETimer_ID_BossDie:
		{
			//boss死亡
			OnPlanDestory();
			//
			RecycleNpcAndMonster();
		}
		break;
	}
}

void GActivityGoblin::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD:
		{
			if (nLen < (int32_t)sizeof(DieEvent))
			{
				return;
			}
			DieEvent *pDieEvent = (DieEvent*)pContext;
			if (pDieEvent->sceneId != m_sceneId)
			{
				return;
			}
			SET_UINT64 setCid;
			setCid.clear();
			if (pDieEvent->monsterId == m_cfg.bossMonsId && pDieEvent->nCid == m_bossCid)
			{
				//参加活动
				Participating(pDieEvent->killerCid);
				//
				OnBossDie(pDieEvent->killerCid);
				setCid.insert(pDieEvent->killerCid);
			}
			else if (pDieEvent->planUid > 0)
			{
				uint64_t npcCid = GetPlanRelate(pDieEvent->planUid);
				GoblinNpcState *pGoblinNpc = GetGoblinNpc(npcCid);
				if (nullptr != pGoblinNpc)
				{
					//这里处理位面怪掉落
					OnMonsDrop(pDieEvent);

					//这里判断位面内怪物是否都死亡,
					//怪物都死亡了,直接移除位面，移除NPC
					bool ballDie = true;
					VEC_UINT64 vecCreature = g_GetPlaneMgr()->GetPlaneNoPlayerList(pDieEvent->planUid);
					VEC_UINT64::iterator iter = vecCreature.begin();
					for (; iter != vecCreature.end(); ++iter)
					{
						Monster *pCreature = GetSceneMonster((*iter));
						if (nullptr != pCreature)
						{
							if (!pCreature->IsDead())
							{
								ballDie = false;
							}
						}
					}

					//
					VEC_UINT64 vecPlayer = g_GetPlaneMgr()->GetPlanePlayerList(pDieEvent->planUid);
					SET_UINT64 setPlayer;
					VEC_UINT64::iterator iterEx = vecPlayer.begin();
					for (; iterEx != vecPlayer.end(); ++iterEx)
					{
						setPlayer.insert((*iterEx));
					}
					//位面怪死亡，需要更新追踪数据
					MultiTrackProto trackProto;
					TrackProtoInfo *proto = trackProto.add_track_info();
					if (nullptr != proto)
					{
						proto->set_mons_id(pDieEvent->monsterId);
						proto->set_mons_num(pDieEvent->count);
					}
					g_GetGActivityMgr()->NotifyUpdateTrack(setPlayer, PRSTE_GOBLIN, trackProto);

					if (ballDie)
					{
						LogDebugFmtPrint("[logic] GActivityGoblin::OnExecute...all monster die...planid:%lu, die_cid:%lu, killer:%lu, npc_cid:%lu ", pDieEvent->planUid,pDieEvent->nCid,pDieEvent->killerCid,npcCid);
						AddWaitPlan(pDieEvent->planUid);
					}
					//
					setCid.insert(pDieEvent->killerCid);
					//参加活动
					Participating(pDieEvent->killerCid);
				}
			}
			if (setCid.size() > 0)
			{
				AddHuoyue(setCid);
			}
		}
		break;
	case EVENT_PLANE_LEAVE:
		{
			if (nLen < (int32_t)sizeof(PlaneLeaveEvent))
			{
				return;
			}
			PlaneLeaveEvent *pLeaveEvent = (PlaneLeaveEvent*)pContext;
			uint64_t npcCid = GetPlanRelate(pLeaveEvent->planeID);
			if (npcCid > 0)
			{
				GoblinNpcState *pGoblinNpc = GetGoblinNpc(npcCid);
				if (nullptr != pGoblinNpc)
				{
					//玩家离开位面，取消追踪显示
					SET_UINT64 setPlayer;
					setPlayer.insert(pLeaveEvent->createCid);
					g_GetGActivityMgr()->NotifyDelTrack(setPlayer, PRSTE_GOBLIN);
				}
			}
		}
		break;
	case EVENT_PLANE_CLOSE:
		{
			if (nLen < (int32_t)sizeof(PlaneCloseEvent))
			{
				return;
			}
			PlaneCloseEvent *pEvent = (PlaneCloseEvent*)pContext;
			uint64_t npcCid = GetPlanRelate(pEvent->planeID);
			if (npcCid > 0)
			{
				GoblinNpcState *pGoblinNpc = GetGoblinNpc(npcCid);
				if (nullptr != pGoblinNpc)
				{
					//移除等待销毁的位面
					DelWaitPlan(pEvent->planeID);
					//位面关闭，npc回复到倒计时状态
					uint64_t intersec = 0;
					if (pGoblinNpc->startTalk > 0)
					{
						uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
						intersec = curTime - pGoblinNpc->startTalk;
						intersec = (intersec > (uint64_t)m_cfg.lifeSec) ? (uint64_t)m_cfg.lifeSec : intersec;
					}				
					pGoblinNpc->state = ACT_NPC_STATE_COUNT_DOWN;
					pGoblinNpc->teamId = 0;
					//npc到时间时间要排除 跟npc对话进入位面，在位面里面花费的时间
					pGoblinNpc->startTime += intersec;
					//移除位面关联
					DelPlanRelate(pEvent->planeID);

					//位面销毁了，通知前端移除追踪
					VEC_UINT64 vecPlayer = g_GetPlaneMgr()->GetPlanePlayerList(pEvent->planeID);
					SET_UINT64 setPlayer;
					VEC_UINT64::iterator iterEx = vecPlayer.begin();
					for (; iterEx != vecPlayer.end(); ++iterEx)
					{
						setPlayer.insert((*iterEx));
					}
					g_GetGActivityMgr()->NotifyDelTrack(setPlayer, PRSTE_GOBLIN);

					//通知前端NPC状态
					ActivityNotifyNpcState rsp;
					rsp.set_state_type(ACT_NPC_STATE_TYPE_UPDATE);
					ActMultNpcStateProto *proto = rsp.mutable_state();
					SetNpcStateProto(*proto, *pGoblinNpc, g_GetGlobalServerTime()->UnixSec());
					//通知NPC状态
					NotifySceneNpcState(rsp);


				}
			}			
		}
		break;
	case EVENT_UNDER_ATTACK:
		{
			//记录那些人对怪物有伤害
			if (nLen < (int32_t)sizeof(skillAttackEvent))
			{
				return;
			}
			skillAttackEvent *pAttackEvent = (skillAttackEvent*)pContext;
			if (pAttackEvent->attacker > 0)
			{
				Player *pPlayer = g_GetCreatureMgr()->GetPlayer(pAttackEvent->attacker);
				if (nullptr != pPlayer && pAttackEvent->sufferedValue > 0)
				{
					m_setHarmChar.insert(pAttackEvent->attacker);
				}
			}
		}
		break;
	}
}

void GActivityGoblin::InitUnionParam(uint32_t unionId, uint32_t sceneId, uint32_t mapId, int32_t unionLev, int32_t averageLev, int32_t collegaLev, int32_t vaultLev)
{
	m_unionId = unionId;
	m_sceneId = sceneId;
	m_mapId = mapId;
	m_lev = unionLev;
	m_averageLev = averageLev;
	m_vaultLev = vaultLev;
}

//玩家进入工会驻地
void GActivityGoblin::OnEnterUnionHome(CharIDType charId)
{
	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		return;
	}
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	ActivityNotifyNpcState rsp;
	rsp.set_state_type(ACT_NPC_STATE_TYPE_UPDATE);
	ActMultNpcStateProto *proto = rsp.mutable_state();
	if (nullptr != proto)
	{
		GoblinNpcMap::iterator iter = m_mapNpc.begin();
		for (; iter != m_mapNpc.end(); ++iter)
		{
			SetNpcStateProto(*proto, iter->second, curTime);
		}
		NotifyPlayerNpcState(pPlayer, rsp);
	}	
	
}


//工会等级更新
void GActivityGoblin::OnUnionLevUpdate(int32_t unionLev)
{
	m_lev = unionLev;
}

int32_t GActivityGoblin::TalkToNpc(Player *pPlayer, uint64_t npcCid, int32_t reply, int8_t &type)
{
	_UNUSE(reply);
	_UNUSE(type);
	if (nullptr == pPlayer)
	{
		return RET_FAIL;
	}
	if (pPlayer->GetSceneId() != m_sceneId)
	{
		return RET_FAIL;
	}
	uint32_t teamId = (uint32_t)pPlayer->GetAttr(C_TEAM_ID);
	if (teamId <= 0)
	{
		return RET_TEAM_NO_TEAM;			//没有队伍
	}
	if (!pPlayer->GetAttr(C_TEAM_LEADER_ID))
	{
		return RET_TEAM_NOT_LEADER;			//不是队长
	}
	GoblinNpcState *pNpcState = GetGoblinNpc(npcCid);
	if (nullptr == pNpcState) //npc不存在
	{
		return RET_ACTIVITY_NPC_NOT_EXIST;
	}
	else if (pNpcState->state != ACT_NPC_STATE_COUNT_DOWN)	
	{
		//npc在对话中
		return RET_ACTIVITY_NPC_IN_TALK;
	}
	else if (teamId == pNpcState->teamId)
	{
		//队伍正在对话中
		return RET_ACTIVITY_TEAM_IN_NPC_TALK;
	}
	SET_UINT64 setTeamChars;
	setTeamChars.clear();
	GetSceneCidByTeamId(teamId, setTeamChars);
	if (setTeamChars.size() <= 0)
	{
		return RET_FAIL;
	}
	VecPoint3 vecPos;
	vecPos.clear();
	Npc *pCreature = GetSceneNpc(pNpcState->npcCid);
	if (nullptr == pCreature)
	{
		LogErrFmtPrint("[logic] GActivityGoblin::TalkToNpc...npc_cid:%lu, unionid:%u, sceneid:%u ", pNpcState->npcCid,m_unionId,m_sceneId);
		return RET_FAIL;
	}
	//创建位面，刷新怪物
	SET_UINT64 setTeamCharsEx = setTeamChars;
	if (!FreshMonster(pNpcState->npcCid, pCreature->GetPos(), teamId, pNpcState->areaId, setTeamChars))
	{
		return RET_FAIL;
	}
	//设置NPC对话状态
	pNpcState->state = ACT_NPC_STATE_TALK;
	pNpcState->teamId = teamId;
	pNpcState->startTalk = g_GetGlobalServerTime()->UnixSec();
	
	//通知npc状态变更
	ActivityNotifyNpcState rsp;
	rsp.set_state_type(ACT_NPC_STATE_TYPE_UPDATE);
	ActMultNpcStateProto *proto = rsp.mutable_state();
	if (nullptr != proto)
	{
		SetNpcStateProto(*proto, *pNpcState, g_GetGlobalServerTime()->UnixSec());
		NotifySceneNpcState(rsp);
	}

	return RET_SUCCESS;
}

GoblinNpcState *GActivityGoblin::GetGoblinNpc(uint64_t npcCid)//根据NPC cid 获取NPC信息
{
	GoblinNpcMap::iterator iter = m_mapNpc.find(npcCid);
	return (iter != m_mapNpc.end()) ? &iter->second : nullptr;
}

GoblinNpcState *GActivityGoblin::GetGoblinNpcByAreaId(uint32_t areaId) //根据 Npc 所在区域ID 获取NPC信息
{
	GoblinNpcMap::iterator iter = m_mapNpc.begin();
	for (; iter != m_mapNpc.end(); ++iter)
	{
		if (iter->second.areaId == areaId)
		{
			return &iter->second;
		}
	}
	return nullptr;
}


//获取指定数量的刷新区域ID
void GActivityGoblin::GetCanFreshArea(SET_UINT32 &setArea)
{
	SET_UINT32::iterator iter = m_cfg.setArea.begin();
	for (; iter != m_cfg.setArea.end(); ++iter)
	{
		uint32_t areaId = (*iter);
		if (nullptr == GetGoblinNpcByAreaId(areaId))
		{
			setArea.insert(areaId);
		}
	}
}

int32_t GActivityGoblin::NpcNum()
{
	return (int32_t)m_mapNpc.size();
}

void GActivityGoblin::DelNpc(uint64_t npcCid)	//移除NPC
{
	m_mapNpc.erase(npcCid);
}
void GActivityGoblin::AddPlanRelate(uint64_t planUid, uint64_t npcCid)	//增加位面关联的NPC
{
	m_mapPlanRelate[planUid] = npcCid;
}

void GActivityGoblin::DelPlanRelate(uint64_t planUid)					//删除位面关联的NPC
{
	m_mapPlanRelate.erase(planUid);
}

uint64_t GActivityGoblin::GetPlanRelate(uint64_t planUid)				//获取位面关联的NPC
{
	MAP_UINT64_UINT64::iterator iter = m_mapPlanRelate.find(planUid);
	return (iter != m_mapPlanRelate.end()) ? iter->second : 0;
}
//刷新生物
void GActivityGoblin::FreshNpc(uint64_t curTime)
{
	if (m_freshBoss) //boss已经刷新完了(所有npc刷完之后才会刷boss)
	{
		return;
	}
	if (m_recycleNum >= m_cfg.maxNpcNum)
	{
		if (!m_bNotifyMonsAllDie)
		{
			m_bNotifyMonsAllDie = true;
			LCGoblinMonsAllDieReq notify;
			notify.set_union_id(m_unionId);
			g_GetLogicService()->SendDataToCenter(EMODULE_ID_ACTIVITY, LOGIC_TO_CENTER_GOBLIN_MONS_ALL_DIE, &notify);
		}
		FreshBoss(m_averageLev);
		return;
	}
	int32_t npcSize = NpcNum();
	if (npcSize >= m_cfg.curNpcNum || m_freshNum >= m_cfg.maxNpcNum)
	{
		return; //当前数量已经足够了,或者已经刷新出最大数量的NPC了
	}
	SET_UINT32 setFresh;
	setFresh.clear();
	int32_t freshNum = m_cfg.curNpcNum - npcSize;
	GetCanFreshArea(setFresh);
	if ((int32_t)setFresh.size() < freshNum)
	{
		LogErrFmtPrint("[logic] GActivityGoblin::FreshCreature...(int32_t)setFresh.size():%d < freshNum:%d  ", setFresh.size(),freshNum);
		return;
	}

	ActivityNotifyNpcState rsp;
	rsp.set_state_type(ACT_NPC_STATE_TYPE_UPDATE);
	ActMultNpcStateProto *proto = rsp.mutable_state();
	for (int32_t i = 0; i < freshNum; ++i)
	{
		SET_UINT32::iterator iter = setFresh.begin();
		uint32_t areaId = (*iter);
		Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(areaId);
		Npc *pNpc = g_GetCreatureMgr()->CreateNpc(m_cfg.npcId, m_sceneId, pos);
		if (nullptr != pNpc)
		{
			setFresh.erase(iter);
			GoblinNpcState info;
			info.npcCid = pNpc->GetCid();
			info.areaId = areaId;
			info.startTime = curTime;
			info.state = ACT_NPC_STATE_COUNT_DOWN;
			m_mapNpc[info.npcCid] = info;
			m_freshNum++;
			//
			SetNpcStateProto(*proto, info, curTime);
			//
			LogDebugFmtPrint("[logic] GActivityGoblin::FreshCreature...CreateNpc...npcid:%u, sceneid:%u,m_mapId:%u, pos:[%f,%f,%fs], areaid:%u, m_recycleNum:%d, ", m_cfg.npcId, m_sceneId, m_mapId, pos.x, pos.y, pos.z, areaId, m_recycleNum);
		}
		else
		{
			LogErrFmtPrint("[logic] GActivityGoblin::FreshCreature...CreateNpc failed...npcid:%u, sceneid:%u,m_mapId:%u, pos:[%f,%f,%fs], areaid:%u , m_recycleNum:%d ", m_cfg.npcId, m_sceneId, m_mapId, pos.x, pos.y, pos.z, areaId, m_recycleNum);
		}
	}

	NotifySceneNpcState(rsp);
}

bool GActivityGoblin::FreshMonster(uint64_t npcCid, Point3<float> midPos,uint32_t teamId, uint32_t areaId, SET_UINT64 &setChars) //刷新怪物
{
	VecPoint3 vecPos;
	vecPos.clear();
	FindBrushPos(midPos, m_cfg.mapFreshMons.size(), vecPos);
	if (vecPos.size() < m_cfg.mapFreshMons.size())
	{
		LogErrFmtPrint("[logic] GActivityGoblin::FreshMonster.....vecPos.size() < m_cfg.mapFreshMons.size()....");
		return false;
	}
	bool isTeam = false;
	if (teamId > 0)
	{
		isTeam = true;
	}
	//创建一个队伍位面
	SET_UINT64::iterator iter = setChars.begin();
	CharIDType charId = (*iter);
	setChars.erase(iter);
	VEC_UINT32 vecNpc;
	uint64_t planUid = g_GetPlaneMgr()->CreatePlane(charId, vecNpc, nullptr, 0, isTeam);
	if (planUid <= 0)
	{
		return false;
	}

	//其他人加入位面
	SET_UINT64::iterator iterEnter = setChars.begin();
	for (; iterEnter != setChars.end(); ++iterEnter)
	{
		g_GetPlaneMgr()->AddCreature(planUid, (*iterEnter));
	}
	//添加NPC对话位面
	AddPlanRelate(planUid,npcCid);
	//
	MAP_INT32_INT32 mapMonsTrack;
	mapMonsTrack.clear();
	//刷怪
	MAP_UINT32_INT32::iterator iterMons = m_cfg.mapFreshMons.begin();
	for (; iterMons != m_cfg.mapFreshMons.end(); ++iterMons)
	{
		int32_t monsNum = iterMons->second;
		int32_t monsId = iterMons->first;
		int32_t totalNum = 0;
		for (int32_t i = 0; i < monsNum; ++i)
		{
			Point3<float> pos = (*vecPos.begin());
			//Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(areaId);
			MonsterExtendInfo extendInfo;
			extendInfo.set_level(m_averageLev);
			Point3<float> curDir = Point3<float>(0, 0, 1);
			MonsCreateParam createParam;
			createParam.createType = EMonsCreateType_Activity;
			createParam.createTypeVal = GetId();
			Monster *pMonster = g_GetCreatureMgr()->CreateMonster(iterMons->first, m_sceneId, pos, createParam, curDir, -1, &extendInfo);
			if (nullptr != pMonster)
			{
				vecPos.erase(vecPos.begin());
				LogDebugFmtPrint("[logic] GActivityGoblin::FreshMonster....CreateMonster....teamid:%u,areaid:%u, sceneid:%u, mapid:%u, monscid:%lu ", teamId,areaId,m_sceneId,m_mapId,pMonster->GetCid());
				g_GetPlaneMgr()->AddCreature(planUid,pMonster->GetCid());
				//
				++totalNum;
			}
		}
		if (totalNum > 0)
		{
			MAP_INT32_INT32::iterator iterTrack = mapMonsTrack.find(monsId);
			if (iterTrack != mapMonsTrack.end())
			{
				iterTrack->second += totalNum;
			}
			else
			{
				mapMonsTrack[monsId] = totalNum;
			}
		}
	}

	//通知追踪数据
	//上面为了创建位面，所以删除了charId,实际在位面里面的玩家是包含 charId的，所以这里把 charId加入到 通知列表中
	setChars.insert(charId);
	MultiTrackProto trackProto;
	MAP_INT32_INT32::iterator iterRes = mapMonsTrack.begin();
	for (; iterRes != mapMonsTrack.end(); ++iterRes)
	{
		TrackProtoInfo *proto = trackProto.add_track_info();
		if (nullptr != proto)
		{
			proto->set_mons_id(iterRes->first);
			proto->set_mons_num(iterRes->second);
		}
	}
	g_GetGActivityMgr()->NotifyAddTrack(setChars, PRSTE_GOBLIN, trackProto);

	return true;
}

void GActivityGoblin::FreshBoss(int32_t averageLev)	//刷新boss怪
{
	MonsterExtendInfo extendInfo;
	extendInfo.set_level(averageLev);
	Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(m_cfg.bornAreaId);
	Point3<float> curDir = Point3<float>(0,0,1);
	MonsCreateParam createParam;
	createParam.createType = EMonsCreateType_Activity;
	createParam.createTypeVal = GetId();
	Monster *pMonster = g_GetCreatureMgr()->CreateMonster(m_cfg.bossMonsId, m_sceneId, pos, createParam, curDir, -1, &extendInfo);
	if (nullptr != pMonster)
	{
		m_bossCid = pMonster->GetCid();
		//需要订阅boss相关时事件，boss掉落是
		SubscribeBossEvent();
		//设置boss已刷新
		m_freshBoss = true;
		//
		LogDebugFmtPrint("[logic] GActivityGoblin::FreshBoss.....unionid:%u, sceneid:%u, mapid:%u ,bossid:%u, averageLev:%d, boss_cid:%lu,  ", m_unionId, m_sceneId, m_mapId, m_cfg.bossMonsId, averageLev, m_bossCid);
	}
	else
	{
		LogErrFmtPrint("[logic] GActivityGoblin::FreshBoss... nullptr == pMonster...bossid:%u, sceneid:%u, averagelev:%d, areaid:%u, pos:%f,%f,%f ", m_cfg.bossMonsId, m_sceneId, averageLev, m_cfg.bornAreaId,pos.x,pos.y,pos.z);
	}
}

void GActivityGoblin::CheckNpc(uint64_t curTime)	//检查NPC生存时间
{
	SET_UINT64 setDel;
	setDel.clear();
	GoblinNpcMap::iterator iterNpc = m_mapNpc.begin();
	while (iterNpc != m_mapNpc.end())
	{
		GoblinNpcState &info = iterNpc->second;
		if (ACT_NPC_STATE_COUNT_DOWN == info.state) //倒计时状态
		{
			if (curTime - info.startTime >= (uint64_t)m_cfg.lifeSec)
			{
				setDel.insert(info.npcCid);
			}
		}
		

		++iterNpc;
	}
	//通知NPC 死亡
	NotifySceneNpcDie(setDel);
	SET_UINT64::iterator iterDel = setDel.begin();
	for (; iterDel != setDel.end(); ++iterDel)
	{
		uint64_t npcCid = (*iterDel);
		NpcLifeEnd(npcCid, true);
	}
}

void GActivityGoblin::NpcLifeEnd(uint64_t npcCid, bool notify)	//npc生命结束
{
	//结束,npc先离开场景
	LogDebugFmtPrint("[logic] GActivityGoblin::NpcLifeEnd...npcCid:%lu, notify:%d ",npcCid,(int32_t)notify);
	Npc *pNpc = GetSceneNpc(npcCid);
	if (nullptr != pNpc)
	{
		if (pNpc->LeaveScene()) //离开场景，设置销毁状态
		{
			//pNpc->SetDestory();
			g_GetCreatureMgr()->WaitDestory(npcCid);
		}
	}
	if (notify)
	{
		//活动NPC消失，偷取工会资金
		NotifyStealMoney();
	}
	DelNpc(npcCid);
	m_recycleNum++;
}

int32_t GActivityGoblin::StealNum()		//偷取的工会资金
{
	int32_t count = 0;
	GoblinStealMap::iterator iter = m_cfg.mapSteal.find(m_lev);
	if (iter != m_cfg.mapSteal.end())
	{
		count = Random((uint32_t)iter->second.minMoney, (uint32_t)iter->second.maxMoney);
	}
	return count;
}

void GActivityGoblin::NotifyStealMoney() //通知偷取工会资金
{
	int32_t money = StealNum();
	if (money > 0)
	{
		//通知中心服偷取工会资金
		LCGoblinStealUnionMoneyReq req;
		req.set_union_id(m_unionId);
		req.set_money(money);
		g_GetLogicService()->SendDataToCenter(EMODULE_ID_ACTIVITY, LOGIC_TO_CENTER_GOBLIN_STEAL_UNION_MONEY, &req);
	}
}

void GActivityGoblin::NotifySceneNpcState(ActivityNotifyNpcState &rsp)  //通知npc状态
{
	if (rsp.has_state())
	{
		const ActMultNpcStateProto proto = rsp.state();
		if (proto.info_size() > 0)
		{
			IDuplicate *pDuplicate = g_GetDuplicateMgr()->GetDuplicate(m_sceneId);
			if (nullptr != pDuplicate)
			{
				pDuplicate->BroadCastData(EMODULE_ID_ACTIVITY, LOGIC_TO_CLIENT_ACTIVITY_NOTIFY_NPC_STATE, &rsp);
			}
		}
	}
}

void GActivityGoblin::NotifyPlayerNpcState(Player *pPlayer, ActivityNotifyNpcState &rsp) //通知玩家NPC状态
{
	if (nullptr == pPlayer || !rsp.has_state())
	{
		return;
	}
	const ActMultNpcStateProto proto = rsp.state();
	if (proto.info_size() > 0)
	{
		pPlayer->SendDataToClient(EMODULE_ID_ACTIVITY, LOGIC_TO_CLIENT_ACTIVITY_NOTIFY_NPC_STATE, &rsp);
	}
}

void GActivityGoblin::NotifySceneNpcDie(SET_UINT64 &setDie)	//通知NPC死亡
{
	if (setDie.size() <= 0)
	{
		return;
	}
	IDuplicate *pDuplicate = g_GetDuplicateMgr()->GetDuplicate(m_sceneId);
	if (nullptr != pDuplicate)
	{
		ActivityNotifyNpcDie notify;
		SET_UINT64::iterator iter = setDie.begin();
		for (; iter != setDie.end(); ++iter)
		{
			notify.add_npc_lst((*iter));
		}
		pDuplicate->BroadCastData(EMODULE_ID_ACTIVITY, LOGIC_TO_CLIENT_ACTIVITY_NOTIFY_NPC_DEAD, &notify);
	}
}

bool GActivityGoblin::GetSceneCidByTeamId(uint32_t teamId, SET_UINT64 &setChars) //获取场景内指定队伍ID的玩家
{
	Scene *pScene = g_GetSceneMgr()->GetScene(m_sceneId);
	if (nullptr == pScene)
	{
		return false; 
	}
	/*const MAP_UINT64_UINT32 *pAllPlayerMap = pScene->GetAllPlayerInScene();
	if (nullptr == pAllPlayerMap)
	{
		return false;
	}*/
	const MAP_Player* pSceneAllPlayers = pScene->GetAllPlayerInScene();
	if (nullptr == pSceneAllPlayers)
	{
		return false;
	}
	//
	MAP_Player::const_iterator iter = pSceneAllPlayers->begin();
	for (; iter != pSceneAllPlayers->end(); ++iter)
	{
		Player *pPlayer = iter->second;
		if (nullptr == pPlayer || pPlayer->IsDestory())
		{
			continue;
		}
		if (teamId == pPlayer->GetAttr(C_TEAM_ID))
		{
			setChars.insert(iter->first);
		}
	}
	return true;
}

int32_t GActivityGoblin::LeftSec(uint64_t curTime, uint64_t startTime)	//剩余时间
{
	int32_t leftsec = curTime - startTime;
	leftsec = (leftsec >= m_cfg.lifeSec) ? 0 : (m_cfg.lifeSec - leftsec);
	return leftsec;
}


void GActivityGoblin::SubscribeBossEvent()		//订阅boss相关事件
{
	//订阅boss被攻击事件
	if (!g_GetEvent()->Subscribe(this, EVENT_UNDER_ATTACK, m_bossCid, 0, "GActivityGoblin"))
	{
		MMOLOG_FMT_ERROR("[logic] GActivityGoblin::SubscribeBossEvent... subcribe boos under attack  event failed....unionid:%u ,mapid:%u , sceneid:%u , bosscid:%lu ", m_unionId, m_mapId, m_sceneId,m_bossCid);
	}
}

void GActivityGoblin::OnBossDie(CharIDType killerCid)
{
	LogDebugFmtPrint("[logic] GActivityGoblin::OnBossDie....unionid:%u, sceneid:%u, mapid:%u boss_cid:%lu ", m_unionId,m_sceneId,m_mapId,m_bossCid);

	LCActivityBroadNotify notify;
	notify.set_union_id(m_unionId);
	notify.set_type(1);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_ACTIVITY, LOGIC_TO_CENTER_ACTIVITY_BROAD_NOTIFY, &notify);


	//取消事件订阅
	g_GetEvent()->UnSubscribeAll(this);
	g_GetTimerAxis()->KillAllTimer(this);
	OnPlanDestory();
	//设置boss死亡定时器
	g_GetTimerAxis()->SetTimer(ETimer_ID_BossDie, 200, this, 1);
	//boss配置
	const MonsterMonsterCfgInfo *pBossCfg = g_GetMonsterMonsterCfgTable()->GetMonsterMonsterCfgInfo(m_cfg.bossMonsId);
	Scene *pScene = g_GetSceneMgr()->GetScene(m_sceneId);
	if (nullptr != pScene && nullptr != pBossCfg)
	{
		Monster *pBossCreature = GetSceneMonster(m_bossCid);
		if (nullptr != pBossCreature)
		{
			Point3<float> pos = pBossCreature->GetPos();
			//对boss造成伤害的玩家都有一份独立掉落
			SET_UINT64::iterator iter = m_setHarmChar.begin();
			for (; iter != m_setHarmChar.end(); ++iter)
			{
				CharIDType charId = (*iter);
				Player *pCreature = pScene->GetPlayer(charId);
				if (nullptr != pCreature && !pCreature->IsDestory())
				{
					SDropSourcePram source;
					source.source = EDropSource_Act;
					source.sourceVal = GetId();
					g_GetDropMgr()->AddDrop(pCreature, pos, pBossCfg->dropDefault, pBossCfg->monsterID, pBossCreature->GetAttr(C_LEVEL), source);
				}
			}
		}
	}

	//boss死亡，完成活动
	FinishActivity();
}

void GActivityGoblin::SetNpcStateProto(ActMultNpcStateProto &rsp, GoblinNpcState &npcState, uint64_t curTime)
{
	ActNpcStateProto *proto = rsp.add_info();
	if (nullptr != proto)
	{
		proto->set_npc_cid(npcState.npcCid);
		proto->set_act_type(GetType());
		proto->set_left_sec(LeftSec(curTime, npcState.startTime));
		proto->set_state(npcState.state);
	}
}

void GActivityGoblin::OnMonsDrop(DieEvent *pDieEvent)  //怪物掉落
{
	if (nullptr == pDieEvent)
	{
		return;
	}
	Creature *pDieCreature = GetSceneMonster(pDieEvent->nCid);
	if (nullptr == pDieCreature)
	{
		return;
	}
	const MonsterMonsterCfgInfo *pMonsterCfg = g_GetMonsterMonsterCfgTable()->GetMonsterMonsterCfgInfo(pDieEvent->monsterId);
	if (nullptr == pMonsterCfg)
	{
		return;
	}
	if (pDieEvent->planUid > 0)
	{
		//位面里面的怪物掉落，都是独立掉落
		Creature *pCreature = GetSceneCreature(pDieEvent->killerCid); 
		SDropSourcePram source;
		source.source = EDropSource_Act;
		source.sourceVal = GetId();
		g_GetDropMgr()->AddDrop(pCreature, pDieCreature->GetPos(), pMonsterCfg->dropDefault, pMonsterCfg->monsterID, pDieCreature->GetAttr(C_LEVEL), source);
	}
}

void GActivityGoblin::RecycleNpcAndMonster()  //回收所有的NPC和怪物
{
	MAP_UINT64_UINT64::iterator iterPlan = m_mapPlanRelate.begin();
	for (; iterPlan != m_mapPlanRelate.end(); ++iterPlan)
	{
		uint64_t planUid = iterPlan->first;
		VEC_UINT64 vecPlayer = g_GetPlaneMgr()->GetPlanePlayerList(planUid);
		VEC_UINT64::iterator iterPlayer = vecPlayer.begin();
		for (; iterPlayer != vecPlayer.end(); ++iterPlayer)
		{
			g_GetPlaneMgr()->LeavePlane((*iterPlayer));
		}
	}
	m_mapPlanRelate.clear();

	GoblinNpcMap::iterator iterNpc = m_mapNpc.begin();
	for (; iterNpc != m_mapNpc.end(); ++iterNpc)
	{
		Npc *pNpc = g_GetCreatureMgr()->GetNpc(iterNpc->first);
		if (nullptr != pNpc)
		{
			if (pNpc->LeaveScene())
			{
				//pNpc->SetDestory();
				g_GetCreatureMgr()->WaitDestory(iterNpc->first);
			}
		}
	}
	m_mapNpc.clear();
	
	//
	if (m_bossCid > 0)
	{
		Monster *pMonster = GetSceneMonster(m_bossCid);
		if (nullptr != pMonster && !pMonster->IsDestory())
		{
			if (pMonster->LeaveScene())
			{
				//pMonster->SetDestory();
				g_GetCreatureMgr()->WaitDestory(m_bossCid);
			}
		}
		m_bossCid = 0;
	}
}

void GActivityGoblin::FindBrushPos(Point3<float> midPos, int32_t count,VecPoint3 &vecPos)
{
	Scene *pScene = g_GetSceneMgr()->GetScene(m_sceneId);
	if (nullptr != pScene)
	{
		pScene->FindPointLstInRect(midPos, vecPos, 2.0f, 2.0f, count);
	}	
}


void GActivityGoblin::AddHuoyue(SET_UINT64 &setCid)//增加哥布林活跃度
{
	SET_UINT64::iterator iterCid = setCid.begin();
	for (; iterCid != setCid.end(); ++iterCid)
	{
		Player *pPlayer = GetScenePlayer((*iterCid));
		if (nullptr != pPlayer)
		{
			HuoYueDuPart *pPart = dynamic_cast<HuoYueDuPart*>(pPlayer->GetPart(PART_HUOYUEDU));
			if (nullptr != pPart)
			{
				pPart->AddHuoYueDuRecord(HYDT_ACTIVITY_GOBLIN);
			}
		}
	}
}

void GActivityGoblin::AddWaitPlan(uint64_t planUid)//增加等待销毁的位面
{
	m_setWaitPlan.insert(planUid);
}

void GActivityGoblin::DelWaitPlan(uint64_t planUid)	//移除等待销毁的位面
{
	m_setWaitPlan.erase(planUid);
}

void GActivityGoblin::OnPlanDestory()				//销毁位面
{
	SET_UINT64::iterator iter = m_setWaitPlan.begin();
	for (; iter != m_setWaitPlan.end(); ++iter)
	{
		uint64_t planUid = (*iter);
		uint64_t npcCid = GetPlanRelate(planUid);
		GoblinNpcState *pGoblinNpc = GetGoblinNpc(npcCid);
		if (nullptr != pGoblinNpc)
		{
			VEC_UINT64 vecPlayer = g_GetPlaneMgr()->GetPlanePlayerList(planUid);
			SET_UINT64 setPlayer;
			setPlayer.clear();
			VEC_UINT64::iterator iterEx = vecPlayer.begin();
			for (; iterEx != vecPlayer.end(); ++iterEx)
			{
				setPlayer.insert((*iterEx));
			}
			//移除位面关联
			DelPlanRelate(planUid);
			//怪物都死亡了，偷取工会资金失败
			NpcLifeEnd(npcCid, false);
			//位面销毁了，通知前端移除追踪
			g_GetGActivityMgr()->NotifyDelTrack(setPlayer, PRSTE_GOBLIN);
			//
			VEC_UINT64::iterator iterPlayer = vecPlayer.begin();
			for (; iterPlayer != vecPlayer.end(); ++iterPlayer)
			{
				g_GetPlaneMgr()->LeavePlane((*iterPlayer));
			}
		}
		else
		{
			LogErrFmtPrint("GActivityGoblin::OnPlanDestory...planUid:%lu ",planUid);
		}
	}
	m_setWaitPlan.clear();
}